package br.ufrj.ia;

import java.util.Random;

import aima.core.agent.Action;
import aima.core.agent.Agent;
import aima.core.agent.EnvironmentState;
import aima.core.agent.Percept;
import aima.core.agent.impl.AbstractEnvironment;
import aima.core.agent.impl.DynamicAction;
import br.ufrj.ia.VacuumEnvPercept;

public class VacuumEnvironment extends AbstractEnvironment {

	public static final Action ACTION_MOVE_LEFT = new DynamicAction("Left");
	public static final Action ACTION_MOVE_RIGHT = new DynamicAction("Right");
	public static final Action ACTION_MOVE_UP = new DynamicAction("Up");
	public static final Action ACTION_MOVE_DOWN = new DynamicAction("Down");
	public static final Action ACTION_SUCK = new DynamicAction("Suck");
	public static final String LOCATION_A = "A";
	public static final String LOCATION_B = "B";
	public static final String LOCATION_C = "C";
	public static final String LOCATION_D = "D";
	
	public enum LocationState {
		Clean, Dirty
	}
	
	public VacuumEnvironment() {
		Random r = new Random(2);
		envState = new VacuumEnvironmentState(
				0 == r.nextInt(2) ? LocationState.Clean : LocationState.Dirty,
				0 == r.nextInt(2) ? LocationState.Clean : LocationState.Dirty, 
				0 == r.nextInt(2) ? LocationState.Clean : LocationState.Dirty,
				0 == r.nextInt(2) ? LocationState.Clean : LocationState.Dirty);
	}
	
	
	public VacuumEnvironment(LocationState locAState, 
			LocationState locBState, 
			LocationState locCState, 
			LocationState locDState) {
		envState = new VacuumEnvironmentState(locAState, locBState, locCState, locDState);
	}
	
	
	protected VacuumEnvironmentState envState = null;
	protected boolean isDone = false;
	
	@Override
	public EnvironmentState executeAction(Agent agent, Action action) {
		
		if (ACTION_MOVE_RIGHT == action 
				&& envState.getAgentLocation(agent) == LOCATION_A) {
			envState.setAgentLocation(agent, LOCATION_B);			
		} else if (ACTION_MOVE_DOWN == action 
				&& envState.getAgentLocation(agent) == LOCATION_B) {
			envState.setAgentLocation(agent, LOCATION_D);
		} else if (ACTION_MOVE_LEFT == action 
				&& envState.getAgentLocation(agent) == LOCATION_D) {
			envState.setAgentLocation(agent, LOCATION_C);
		} else if (ACTION_MOVE_UP == action 
				&& envState.getAgentLocation(agent) == LOCATION_C) {
			envState.setAgentLocation(agent, LOCATION_A);
		} else if (ACTION_SUCK == action) {
			if (LocationState.Dirty == envState.getLocationState(envState
					.getAgentLocation(agent))) {
				envState.setLocationState(envState.getAgentLocation(agent),
						LocationState.Clean);
				updatePerformanceMeasure(agent, 10);
			}
		} else if (action.isNoOp()) {
			isDone = true;
		}
		
		return envState;
	}

	@Override
	public EnvironmentState getCurrentState() {
		return envState;
	}

	@Override
	public Percept getPerceptSeenBy(Agent anAgent) {
		String agentLocation = envState.getAgentLocation(anAgent);
		return new VacuumEnvPercept(agentLocation, envState.getLocationState(agentLocation));
	}

	@Override
	public boolean isDone() {
		return super.isDone() || isDone;
	}
	

	public void addAgent(Agent a, String location) {
		// Ensure the agent state information is tracked before
		// adding to super, as super will notify the registered
		// EnvironmentViews that is was added.
		envState.setAgentLocation(a, location);
		super.addAgent(a);
	}

	public LocationState getLocationState(String location) {
		return envState.getLocationState(location);
	}

	public String getAgentLocation(Agent a) {
		return envState.getAgentLocation(a);
	}
}
